﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using APNS.NET;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;

namespace APNSUnitTests.given_an_apnsconnectionpool
{
    
    public class when_I_release_a_connection
    {
        protected MockRepository mocks;
        protected Queue<IApnsConnection> connections;
        protected ApnsConnectionPool connectionPool;

        public virtual void Setup()
        {
            mocks = new MockRepository();
            connections = new Queue<IApnsConnection>();
            connectionPool = new ApnsConnectionPool(connections.Dequeue);
        }

        [TestClass]
        public class and_there_were_no_errors : when_I_release_a_connection
        {

            [TestInitialize]
            public override void Setup()
            {
                base.Setup();
            }

            [TestMethod]
            public void then_the_connection_should_go_back_into_the_pool()
            {
                var stubConnection = mocks.Stub<IApnsConnection>();
                stubConnection.Stub(c => c.Connected).Return(true);

                connections.Enqueue(stubConnection);

                // Put a connection in  the pool
                mocks.ReplayAll();
                // Release the connection
                connectionPool.ReleaseConnection(connectionPool.GetConnection(), false);

                // Get the connection out of the pool
                var connection = connectionPool.GetConnection();
                Assert.AreSame(stubConnection, connection);
            }
        }

        [TestClass]
        public class and_there_were_errors : when_I_release_a_connection
        {

            [TestInitialize]
            public override void Setup()
            {
                base.Setup();
            }

            [TestMethod]
            public void then_the_connection_should_not_go_back_into_the_pool()
            {
                var stubConnection1 = mocks.Stub<IApnsConnection>();
                var stubConnection2 = mocks.Stub<IApnsConnection>();
                
                stubConnection1.Stub(c => c.Connected).Return(true);
                stubConnection1.Expect(c => c.Close());

                stubConnection2.Stub(c => c.Connected).Return(true);                
                
                connections.Enqueue(stubConnection1);
                connections.Enqueue(stubConnection2);

                // Put a connection in  the pool
                mocks.ReplayAll();
                // Release the connection
                connectionPool.ReleaseConnection(connectionPool.GetConnection(), true);

                // Get the connection out of the pool
                var connection = connectionPool.GetConnection();
                Assert.AreSame(stubConnection2, connection);

                mocks.VerifyAll();
            }
        }

        [TestClass]
        public class and_the_connection_is_closed : when_I_release_a_connection
        {

            [TestInitialize]
            public override void Setup()
            {
                base.Setup();
            }

            [TestMethod]
            public void then_the_connection_should_not_go_back_into_the_pool()
            {
                var stubConnection1 = mocks.Stub<IApnsConnection>();
                var stubConnection2 = mocks.Stub<IApnsConnection>();

                stubConnection1.Stub(c => c.Connected).Return(false);
                stubConnection1.Expect(c => c.Close());

                stubConnection2.Stub(c => c.Connected).Return(true);

                connections.Enqueue(stubConnection1);
                connections.Enqueue(stubConnection2);

                // Put a connection in  the pool
                mocks.ReplayAll();
                // Release the connection
                connectionPool.ReleaseConnection(connectionPool.GetConnection(), false);

                // Get the connection out of the pool
                var connection = connectionPool.GetConnection();
                Assert.AreSame(stubConnection2, connection);

                mocks.VerifyAll();
            }
        }

    }
}

